package com.rulin.asp.util;

import static org.apache.commons.collections4.ListUtils.emptyIfNull;
import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
import static org.apache.commons.lang3.Validate.noNullElements;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Triple;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;

import com.google.common.base.Function;
import com.google.common.collect.Lists;

public class Excel<T> {
	
	/**
	 * 将数据列表转换成excel对象
	 * @param clazz
	 * @param rows
	 * @throws IOException
	 */
	public Excel(Class<?> clazz, List<T> rows) throws IOException {
		List<Triple<String, String, String>> titles = new ArrayList<Triple<String, String, String>>();
		
		Field[] fields = clazz.getDeclaredFields();
		for (Field field : noNullElements(fields)) {
			ExcelFieldTitle efield = field.getAnnotation(ExcelFieldTitle.class);
			if (efield != null) {
				titles.add(Triple.of(field.getName(), defaultIfBlank(efield.value(), ""), defaultIfBlank(efield.width(), "")));
			}
		}
		
		
		this.wb               = new HSSFWorkbook();
		this.titleCellStyle   = createTitleCellStyle();
		this.contentCellStyle = createContentStyle();
		
		List<String> titleNames = getTitleNames(titles);
		
		List<List<T>> prows = Lists.partition(emptyIfNull(rows), SHEET_MAX_ROW);
		
		for (List<T> part : prows) {
			
			HSSFSheet sheet = wb.createSheet();
			
			setTitle(sheet, titleNames);
			setContexts(sheet, titles, part);
			
			/*setSheetAutoSizeColumn(0,sheet);*/
			setSheetSizeColumn(0, titles, sheet);
		}
		
		if (prows.isEmpty()) { // 当无记录时，创建空sheet，附上字段标题。
			HSSFSheet sheet = wb.createSheet();
			setTitle(sheet, titleNames);
			/*setSheetAutoSizeColumn(0,sheet);*/
			setSheetSizeColumn(0, titles, sheet);
		}
	}
	private void setSheetSizeColumn(int rowIndex, List<Triple<String, String, String>> titles, HSSFSheet sheet) {

		int coloumNum=sheet.getRow(rowIndex).getPhysicalNumberOfCells();
		for(int i = 0;i<coloumNum;i++){
			Triple<String, String, String> lmr = titles.get(i);
			if(null == lmr || StringUtils.isEmpty(lmr.getRight())){
				int length = lmr.getMiddle().getBytes().length;
				sheet.setColumnWidth(i, length*256);
			}else {
				try{
					Integer width = Integer.parseInt(lmr.getRight());
					sheet.setColumnWidth(i, width*1000);
				}catch(Exception e){
					sheet.autoSizeColumn((short)i);
				}
			}
		}
		
	}

	protected List<String> getTitleNames(List<Triple<String, String, String>> titles) {
		return Lists.transform(titles, new Function<Triple<String, String, String>, String>() {

			@Override
			public String apply(Triple<String, String, String> input) {
				return input.getMiddle();
			}});
	}
	
	protected void setContexts(HSSFSheet sheet, List<Triple<String, String, String>> titles, List<T> rows) {
		int i = 1;
		for (T t : rows) {
			HSSFRow frow = sheet.createRow(i);
			
			int j = 0;
			for (Triple<String, String, String> lmr : titles) {
				HSSFCell cell = frow.createCell(j);
				cell.setCellStyle(contentCellStyle);
				cell.setAsActiveCell();
				
				String fieldName = lmr.getLeft();
				String value = getFieldValue(t, fieldName);
				cell.setCellValue(value);
				
				j++;
			}
			
			i++;
		}
	}
	
	public void export(OutputStream os) throws IOException {
		wb.write(os);
		os.flush();
	}

	protected final static int SHEET_MAX_ROW = 60000;
	
	
	protected HSSFWorkbook wb;
	
	protected HSSFCellStyle titleCellStyle;
	
	protected HSSFCellStyle contentCellStyle;

	
	protected void setSheetAutoSizeColumn(int rowIndex,HSSFSheet sheet){
		int coloumNum=sheet.getRow(rowIndex).getPhysicalNumberOfCells();
		for(int i = 0;i<coloumNum;i++){
			sheet.autoSizeColumn((short)i); //调整列宽度
		}
	}
	
	protected void setTitle(HSSFSheet sheet, List<String> titleNames) {
		HSSFRow head = sheet.createRow(0);
		
		int i = 0;
		for (String titleName : titleNames) {
			HSSFCell cell = head.createCell(i);
			
			cell.setCellType(HSSFCell.CELL_TYPE_STRING);
			cell.setCellStyle(titleCellStyle);
			cell.setAsActiveCell();
			
			cell.setCellValue(titleName);
			
			i++;
		}
	}
	
	
	/**
	 * 创建每列的内容的样式
	 */
	protected  HSSFCellStyle createTitleCellStyle() {
		HSSFCellStyle style = wb.createCellStyle();
		
		style.setFillForegroundColor(HSSFColor.GREY_25_PERCENT.index);// 设置填充背景为浅灰色
		
		// 设置边框样式
		style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
		style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
		style.setBorderRight(HSSFCellStyle.BORDER_THIN);
		style.setBorderTop(HSSFCellStyle.BORDER_THIN);
		
//		style.setAlignment(HSSFCellStyle.ALIGN_CENTER); //居中
		style.setAlignment(HSSFCellStyle.ALIGN_LEFT); //居中
		
		style.setFont(createTitleFont());// 把字体应用到当前的样式
		
		return style;
	}

	/**
	 * 创建每列的内容的文字样式
	 */
	protected HSSFFont createTitleFont() {
		HSSFFont font = wb.createFont();
		font.setColor(HSSFColor.BLACK.index);// 设置字体为紫色
		font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);// 设置字体为加粗
		font.setFontHeightInPoints((short)12);// 设置字体大小为12号
		return font;
	}
	

	protected String getFieldValue(T t, String fieldName) {
		Field field = null;
		try {
			field = t.getClass().getDeclaredField(fieldName);
		} catch (NoSuchFieldException | SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Object object = null;
		try {
			object = field.get(fieldName);
		} catch (IllegalArgumentException | IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if(object instanceof Date){
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			return sdf.format(object);
		}
		return object == null ? "" : object.toString();
		
//		try {
//			Object value = Ognl.getValue(Validate.notBlank(fieldName), Validate.notNull(t));
//			if(value instanceof Date){
//				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//				return sdf.format(value);
//			}
//			return value == null ? "" : value.toString();
//		}
//		catch (OgnlException e) {
//			throw new IllegalStateException(e);
//		}
	}



	/**
	 * 设置每列的内容的样式
	 */
	private  HSSFCellStyle createContentStyle() {
		HSSFCellStyle style = wb.createCellStyle();
		style.setFillForegroundColor(HSSFColor.WHITE.index);
		style.setFont(createContentFont());
		// 设置边框样式
		style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
		style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
		style.setBorderRight(HSSFCellStyle.BORDER_THIN);
		style.setBorderTop(HSSFCellStyle.BORDER_THIN);
//		style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		style.setAlignment(HSSFCellStyle.ALIGN_LEFT);
		return style;
	}

	/**
	 * 设置每列的内容的文字样式
	 */
	protected  HSSFFont createContentFont() {
		HSSFFont font = wb.createFont();
		Short st = 11;
		font.setColor(HSSFColor.BLACK.index);
		font.setFontHeightInPoints(st);
		return font;
	}

}
